<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div>
        <button @click="p">测试</button>
    </div>
    <script>
        function myPromise(fn) {
            const _this = this
            _this.status = 'pending'
            _this.resolveData = '';
            _this.cacheFn = {}

            function resolve(data) {
                if (_this.status !== 'pending') return
                _this.status = 'success';
                _this.resolveData = data;
                if (_this.cacheFn.resolveFn) {
                    _this.cacheFn.resolveFn(data)
                }
            }
            function reject(data) {
                if (_this.status !== 'pending') return
                _this.status = 'failed';
                _this.resolveData = data;
                if (_this.cacheFn.rejectFn) {
                    _this.cacheFn.rejectFn(data)
                }
            }

            try {
                fn(resolve, reject)
            } catch(e) {
                console.log('myPromise', e)
                reject(e)
            }
            
        }

        /**
         * promise实例点出的函数其实都是then 
         * catch finally其实都是在调用then方法，只是换了个名字
         * then函数的return还是一个promise 所以then之后还是点出then以及catch finally
        */
        myPromise.prototype.then = function(resolveFn, rejectFn) {
            console.log('myPromise.prototype.then', this.status)
            
            if (this.status === 'success') {
                resolveFn(this.resolveData)
                return new myPromise((resolve, reject) => {
                    resolve(this.resolveData)
                })
            }
            if (this.status === 'failed') {
                rejectFn && rejectFn(this.resolveData)
                // 如果不是通过then传递reject，丢到catch方法中处理
                return new myPromise((resolve, reject) => {
                    reject(this.resolveData)
                })
            }
            if (this.status === 'pending') {
                // 如果promise中有异步操作，resolve是在异步完成后才调用，那么then在执行的时候状态就还没有改变
                // 所以这时要缓存回调函数，等异步结束后再执行
                this.cacheFn.resolveFn = resolveFn;
                this.cacheFn.rejectFn = rejectFn;
            } 
        }

        myPromise.prototype.catch = function(rejectFn) {
            console.log('myPromise.prototype.catch', this.status)
            if (this.status === 'failed') {
                rejectFn && rejectFn(this.resolveData)
                return new myPromise((resolve, reject) => {
                    resolve(this.resolveData)
                })
            }
        }

        myPromise.prototype.finally = function(fn) {
            if (this.status !== 'pending') {
                fn(this.resolveData)
            }
        }

        let p = new myPromise((resolve, reject) => {
            // resolve('ok')
            // reject('no')
            // throw 'error'

            // setTimeout(() => {
                resolve('ok')
                // reject('no')
            // }, 2000)
        })
        // console.log(p)
        p.then((res) => {
            console.log('example1 res', res)
        }, (err) => {
            console.log('example1 err', err)
        })

        p.then((res) => {
            console.log('example2 res', res)
        }).catch((err) => {
            console.log('example2 err', err)
        })

        p.then((res) => {
            console.log('then111', res)
            return new myPromise(resolve => {
                resolve('ok1')
            })
        }).then((res) => {
            console.log('then222', res)
        }).catch(err => {
            console.log('catch', err)
        }).finally(() => {
            console.log('finally')
        })
    </script>
</body>
</html>